//***************************************************************************
//   Copyright(c)2020, Xidian University D405.
//           All rights reserved
//
//   File name       :   axi_fifo_mux.v
//   Module name     :   axi_fifo_mux
//   Author          :   Zhao Yuchen
//   Date            :   2022/04/07
//   Version         :   v1.00
//   Edited by       :   Zhao Yuchen
//***************************************************************************
module axi_fifo_mux #
(
	parameter AXI_DATA_WIDTH = 128, 
	parameter AXI_LIB_WIDTH  = 11
)
(
    /*** AXI FIFO Control Ports ***/
	input  wire                         axiw_fifo_rd_en_i,
	output reg  [AXI_DATA_WIDTH-1 : 0]  axiw_fifo_rd_data_o,
	output reg                          axiw_fifo_rd_valid_o,
	output reg                          axiw_fifo_rd_empty_o,
	input  wire [1 : 0]                 axiw_data_or_desc_sel_i,
	input  wire [1 : 0]                 axiw_desc_fifo_sel_i,
	
	input  wire                         axir_fifo_wr_en_i,
	input  wire [AXI_DATA_WIDTH-1 : 0]  axir_fifo_wr_data_i,
	output reg                          axir_fifo_wr_full_o,
	input  wire [1 : 0]                 axir_data_or_desc_sel_i,
	input  wire [1 : 0]                 axir_desc_fifo_sel_i,
	input  wire [1 : 0]                 axir_txfifo_10g40g_sel_i,
	
	/****************************************************************/
	/*** RxFIFO ***/
	output reg                          rxfifo_data_rd_en_o,
	input  wire [AXI_DATA_WIDTH-1 : 0]  rxfifo_data_dout_i,
	input  wire                         rxfifo_data_valid_i,
	//input  wire                         rxfifo_empty_i,
    
	/*** AXI Write Back Descriptors FIFO ***/
	output reg                          axiw_rxdesc_fifo_rd_en_o,
	input  wire [AXI_DATA_WIDTH-1 : 0]  axiw_rxdesc_fifo_dout_i,
	input  wire                         axiw_rxdesc_fifo_empty_i,
	
	output reg                          axiw_txdesc_fifo_rd_en_o,
	input  wire [AXI_DATA_WIDTH-1 : 0]  axiw_txdesc_fifo_dout_i,
	input  wire                         axiw_txdesc_fifo_empty_i,
	
	/****************************************************************/
    /*** TxFIFO ***/
	output reg                          txfifo_data_wr_en_40g_o,
	output reg  [AXI_DATA_WIDTH-1 : 0]  txfifo_data_din_40g_o,
	input  wire                         txfifo_full_40g_i,
	//output reg                          txfifo_leng_wr_en_40g_o,
	//output reg  [AXI_LIB_WIDTH-1 : 0]   txfifo_leng_din_40g_o,
	
	output reg                          txfifo_data_wr_en_10g_o,
	output reg  [AXI_DATA_WIDTH-1 : 0]  txfifo_data_din_10g_o,
	input  wire                         txfifo_full_10g_i,
	//output reg                          txfifo_leng_wr_en_10g_o,
	//output reg  [AXI_LIB_WIDTH-1 : 0]   txfifo_leng_din_10g_o,
	
	/*** AXI Read Descriptors FIFO ***/
	output reg                          axir_rxdesc_fifo_wr_en_o,
	output reg  [AXI_DATA_WIDTH-1 : 0]  axir_rxdesc_fifo_din_o,
	input  wire                         axir_rxdesc_fifo_full_i,
	
	output reg                          axir_txdesc_fifo_wr_en_o,
	output reg  [AXI_DATA_WIDTH-1 : 0]  axir_txdesc_fifo_din_o,
	input  wire                         axir_txdesc_fifo_full_i
);
	always @(*)
    begin
        case({axiw_desc_fifo_sel_i, axiw_data_or_desc_sel_i})
			4'b0101, 4'b1001: //axi write data from rxfifo
			begin
			    //RxFIFO
				rxfifo_data_rd_en_o  = axiw_fifo_rd_en_i;
				//axiw rxdesc FIFO
				axiw_rxdesc_fifo_rd_en_o = 1'b0;
				//axiw txdesc FIFO
				axiw_txdesc_fifo_rd_en_o = 1'b0;
				//AXI WRITE DATA
				axiw_fifo_rd_data_o  = rxfifo_data_dout_i;
				axiw_fifo_rd_valid_o = rxfifo_data_valid_i;
				//AXI FIFO STATE
				axiw_fifo_rd_empty_o = 1'b0;//rxfifo_empty_i; rxfifo empty is mean no "length" in fifo
			end
			4'b0110: //axi write desc from rxdesc fifo
			begin
				//RxFIFO
				rxfifo_data_rd_en_o  = 1'b0;
				//axiw rxdesc FIFO
				axiw_rxdesc_fifo_rd_en_o = axiw_fifo_rd_en_i;
				//axiw txdesc FIFO
				axiw_txdesc_fifo_rd_en_o = 1'b0;
				//AXI WRITE DATA
				axiw_fifo_rd_data_o  = axiw_rxdesc_fifo_dout_i;
				axiw_fifo_rd_valid_o = 1'b0;
				//AXI FIFO STATE
				axiw_fifo_rd_empty_o = axiw_rxdesc_fifo_empty_i;
			end
			4'b1010: //axi write desc from txdesc fifo
			begin
				//RxFIFO
				rxfifo_data_rd_en_o  = 1'b0;
				//axiw rxdesc FIFO
				axiw_rxdesc_fifo_rd_en_o = 1'b0;
				//axiw txdesc FIFO
				axiw_txdesc_fifo_rd_en_o = axiw_fifo_rd_en_i;
				//AXI WRITE DATA
				axiw_fifo_rd_data_o  = axiw_txdesc_fifo_dout_i;
				axiw_fifo_rd_valid_o = 1'b0;
				//AXI FIFO STATE
				axiw_fifo_rd_empty_o = axiw_txdesc_fifo_empty_i;
			end
			default:
			begin
				//RxFIFO
				rxfifo_data_rd_en_o  = 1'b0;
				//axiw rxdesc FIFO
				axiw_rxdesc_fifo_rd_en_o = 1'b0;
				//axiw txdesc FIFO
				axiw_txdesc_fifo_rd_en_o = 1'b0;
				//AXI WRITE DATA
				axiw_fifo_rd_data_o  = 'd0;
				axiw_fifo_rd_valid_o = 1'b0;
				//AXI FIFO STATE
				axiw_fifo_rd_empty_o = 1'b0;
			end
        endcase
    end
	
	always @(*)
	begin
		case ({axir_txfifo_10g40g_sel_i, axir_desc_fifo_sel_i, axir_data_or_desc_sel_i})
			6'b010101, 6'b011001: //axi read data to TxFIFO 10g
			begin
				//TxFIFO 10g
				txfifo_data_wr_en_10g_o = axir_fifo_wr_en_i;
				txfifo_data_din_10g_o   = axir_fifo_wr_data_i;
				//TxFIFO 40g
				txfifo_data_wr_en_40g_o = 1'b0;
				txfifo_data_din_40g_o   = 'd0;
				//axir rxdesc FIFO
				axir_rxdesc_fifo_wr_en_o = 1'b0;
				axir_rxdesc_fifo_din_o   = 'd0;
				//axir txdesc FIFO
				axir_txdesc_fifo_wr_en_o = 1'b0;
				axir_txdesc_fifo_din_o   = 'd0;
				//AXI FIFO STATE
				axir_fifo_wr_full_o      = txfifo_full_10g_i;
			end
			6'b100101, 6'b101001: //axi read data to TxFIFO 40g
			begin
				//TxFIFO 10g
				txfifo_data_wr_en_10g_o = 1'b0;
				txfifo_data_din_10g_o   = 'd0; 
				//TxFIFO 40g
				txfifo_data_wr_en_40g_o = axir_fifo_wr_en_i;
				txfifo_data_din_40g_o   = axir_fifo_wr_data_i;
				//axir rxdesc FIFO
				axir_rxdesc_fifo_wr_en_o = 1'b0;
				axir_rxdesc_fifo_din_o   = 'd0;
				//axir txdesc FIFO
				axir_txdesc_fifo_wr_en_o = 1'b0;
				axir_txdesc_fifo_din_o   = 'd0;
				//AXI FIFO STATE
				axir_fifo_wr_full_o      = txfifo_full_40g_i;
			end
			6'b010110, 6'b100110: //axi read desc to rxdesc FIFO
			begin
				//TxFIFO 10g
				txfifo_data_wr_en_10g_o = 1'b0;
				txfifo_data_din_10g_o   = 'd0; 
				//TxFIFO 40g
				txfifo_data_wr_en_40g_o = 1'b0;
				txfifo_data_din_40g_o   = 'd0; 
				//axir rxdesc FIFO
				axir_rxdesc_fifo_wr_en_o = axir_fifo_wr_en_i;
				axir_rxdesc_fifo_din_o   = axir_fifo_wr_data_i;
				//axir txdesc FIFO
				axir_txdesc_fifo_wr_en_o = 1'b0;
				axir_txdesc_fifo_din_o   = 'd0;
				//AXI FIFO STATE
				axir_fifo_wr_full_o      = axir_rxdesc_fifo_full_i;
			end
			6'b011010, 6'b101010: //axi read desc to txdesc FIFO
			begin
				//TxFIFO 10g
				txfifo_data_wr_en_10g_o = 1'b0;
				txfifo_data_din_10g_o   = 'd0; 
				//TxFIFO 40g
				txfifo_data_wr_en_40g_o = 1'b0;
				txfifo_data_din_40g_o   = 'd0; 
				//axir rxdesc FIFO
				axir_rxdesc_fifo_wr_en_o = 1'b0;
				axir_rxdesc_fifo_din_o   = 'd0; 
				//axir txdesc FIFO
				axir_txdesc_fifo_wr_en_o = axir_fifo_wr_en_i;
				axir_txdesc_fifo_din_o   = axir_fifo_wr_data_i;
				//AXI FIFO STATE
				axir_fifo_wr_full_o      = axir_txdesc_fifo_full_i;
			end
			default:
			begin
				//TxFIFO 10g
			    txfifo_data_wr_en_10g_o = 1'b0;
			    txfifo_data_din_10g_o   = 'd0; 
			    //TxFIFO 40g
			    txfifo_data_wr_en_40g_o = 1'b0;
			    txfifo_data_din_40g_o   = 'd0; 
			    //axir rxdesc FIFO
			    axir_rxdesc_fifo_wr_en_o = 1'b0;
			    axir_rxdesc_fifo_din_o   = 'd0; 
			    //axir txdesc FIFO
			    axir_txdesc_fifo_wr_en_o = 1'b0;
			    axir_txdesc_fifo_din_o   = 'd0; 
			    //AXI FIFO STATE
			    axir_fifo_wr_full_o      = 1'b0;
			end
		endcase
	end
	
endmodule